home *** CD-ROM | disk | FTP | other *** search
/ Cream of the Crop 1 / Cream of the Crop 1.iso / UTILITY / MIR105.ARJ / MIR_WP51.EXE / lha / A_PATTRN.C < prev    next >
Text File  |  1992-05-02  |  11KB  |  345 lines

  1. /*
  2.  *  usage:  a_pattrn  file_name  key  [ /x ] [ bytes_before ] > report
  3.  *              "/x" = include hex, show only 16 bytes instead of 40
  4.  * A_PATTRN List every occurrence of a key character or string in a file.
  5.  *          Show 3 (or "bytes_before", range 0 to 15) bytes prior to the
  6.  *          key each time.  Normally show a total of 40 bytes each time
  7.  *          the key is found; if the "/x" argument is set, show only 16
  8.  *          bytes, but in hex and ASCII both.  The key may be from 1 to
  9.  *          16 characters.  Within the key, any non-printing characters,
  10.  *          characters which may confuse DOS (> or < or |), linefeeds,
  11.  *          blanks, backslash, etc. must be shown in hex form...  a
  12.  *          backslash and 2 hex digits.  Examples:
  13.  *              a_pattrn herfile  \8E  >  herfile.8e
  14.  *              a_pattrn yourfile  *  7  >  yourfile.ast
  15.  *              a_pattrn myfile  Mother
  16.  *              a_pattrn hisfile  \94\05ke\ff  0  >  5char.pat
  17.  *
  18.  *  input:  Any file whatsoever.
  19.  *
  20.  *  output: One line for each occurrence of the target byte(s) in the file.
  21.  *          Sort the result to make patterns show up more clearly.
  22.  *
  23.  *  writeup: MIR TUTORIAL ONE, topic 5
  24.  *
  25.  *  Written:    Douglas Lowry    Jan 07 92
  26.  *  Modified:   Douglas Lowry    Apr 03 92  Modify arguments
  27.  *              Copyright (C) 1992  Marpex Inc.
  28.  *
  29.  *  For further information, contact
  30.  *              Innotech Inc., 110 Silver Star Blvd., # 107,
  31.  *              Scarborough, Ontario  Canada   M1V 5A2
  32.  *              Tel.  416 321-3838   FAX  416 321-0095
  33.  *
  34.  *  This program is free software; you may redistribute it and/or
  35.  *  modify it under the terms of the GNU General Public License as
  36.  *  published by the Free Software Foundation; either version 2 of
  37.  *  the License, or (at your option) any later version.
  38.  *
  39.  *  This program is distributed in the hope that it will be useful,
  40.  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  41.  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  42.  *  GNU General Public License for more details.
  43.  *
  44.  *  You should have received a copy of the GNU General Public
  45.  *  License (file 05LICENS) along with this program; if not,
  46.  *  write to the Free Software Foundation, Inc., 675 Mass Ave,
  47.  *  Cambridge, MA 02139, USA.
  48.  */
  49.  
  50. #include <stdio.h>
  51. #include <stdlib.h>
  52. #include <dos.h>
  53. #include <ctype.h>
  54. #include <direct.h>
  55.  
  56. #define  BIGBUF     2048
  57. #define  repeat     for(;;)
  58.  
  59. typedef     enum    _bool
  60.         { FALSE = 0, TRUE = 1 } Bool ;
  61. /*
  62.  *  declarations
  63.  */
  64.  
  65.     void    process( ), Usage_( ), line_out( );
  66.     unsigned long int   xtol_n( );
  67.     char    *Cmdname_()     { return( "a_pattrn" ) ;    }
  68.  
  69. /*
  70.  *  MAIN -
  71.  */
  72.  
  73. main( argc, argv )
  74.     int argc;
  75.     char    **argv;
  76. {
  77.     FILE                *fp_in ;
  78.     Bool                ascii ;     /*  ASCII display only requested */
  79.     int                 len, i ;
  80.     unsigned long int   l_test ;
  81.     unsigned char       key[16];    /*  character requested by user  */
  82.     short int           precede,    /*  bytes before key to be shown */
  83.                         key_len,
  84.                         pt ;        /*  pointer within "key" argument*/
  85.  
  86. /*  usage:  a_pattrn  file_name  key  [ -x ] [ bytes_before ] > report*/
  87.  
  88.     if( argc < 3 || argc > 5 )
  89.         Usage_();
  90.  
  91.     if(( fp_in = fopen( argv[1], "r+b" )) == NULL )
  92.     {
  93.         fprintf( stderr, "Unable to open input file %s\n", argv[1] );
  94.         Usage_() ;
  95.     }
  96.  
  97.     pt = 0 ;
  98.     for( key_len = 0 ; key_len < 16 ; key_len++ )
  99.     {
  100.         if( !argv[2][pt] )
  101.             break ;
  102.         if( argv[2][pt] != 0x5c )    /*  not backslash = printable */
  103.         {
  104.             key[ key_len ] = ( unsigned char ) argv[2][pt] ;
  105.             pt++ ;
  106.         }
  107.         else
  108.         {
  109.             l_test = xtol_n( &argv[2][pt+1], 2 ) ;
  110.             if( l_test > 0xff )
  111.                 Usage_();
  112.             key[ key_len ] = ( unsigned char ) l_test ;
  113.             pt += 3 ;
  114.         }
  115.     }
  116.  
  117.     precede = 3 ;
  118.     ascii = TRUE ;
  119.  
  120.     for( i = 3; i < argc ; i++ )
  121.     {
  122.         if( islower( argv[i][1] ))
  123.             argv[i][1] = toupper( argv[i][1] ) ;
  124.         if( argv[i][1] == 'X' && ( argv[i][0] == '/' || argv[i][0] == '-' ))
  125.             ascii = FALSE ;
  126.         else
  127.         {
  128.             precede = atoi( argv[i] );
  129.             if( precede > 16 - key_len )
  130.                 precede = 16 - key_len ;
  131.             if( precede < 0 )
  132.                 precede = 0 ;
  133.         }
  134.     }
  135.  
  136.     process( key, key_len, ascii, precede, fp_in );
  137.  
  138.     fclose( fp_in );
  139.  
  140.     exit( 0 );
  141. }
  142.     void
  143. Usage_( )
  144. {
  145.     fprintf( stderr,
  146.         "usage:  %s file_name  key  [ /x ] [ bytes_before ] > report\n\
  147.              \"/x\" = include hex, show only 16 bytes instead of 40\n\
  148.         List every occurrence of a key character or string in a file.\n\
  149.         Show 3 (or \"bytes_before\", range 0 to 15) bytes prior to the\n",
  150.                 Cmdname_() );
  151.     fprintf( stderr,
  152. "        key each time.  Normally show a total of 40 bytes each time\n\
  153.         the key is found; if the \"/x\" argument is set, show only 16\n\
  154.         bytes, but in hex and ASCII both.  The key may be from 1 to\n\
  155.         16 characters.  Within the key, any non-printing characters,\n" );
  156.     fprintf( stderr,
  157. "        characters which may confuse DOS (> or < or |), linefeeds,\n\
  158.         blanks, backslash, etc. must be shown in hex form...  a\n\
  159.         backslash and 2 hex digits.  Examples:\n\
  160.             a_pattrn herfile  \8E  >  herfile.8e\n\
  161.             a_pattrn yourfile  *  7  >  yourfile.ast\n" ) ;
  162.     fprintf( stderr,
  163. "            a_pattrn myfile  Mother\n\
  164.             a_pattrn hisfile  \\94\\05ke\\ff  0  >  5char.pat\n\n\
  165. input:  Any file whatsoever.\n\n\
  166. output: One line for each occurrence of the target byte(s) in the file.\n\
  167.         Sort the result to make patterns show up more clearly.\n\n\
  168. writeup: MIR TUTORIAL ONE, topic 5\n" ) ;
  169.     exit( 1 );
  170. }
  171. /*
  172.  *  XTOL_N  Converts a specified number of bytes of hexadecimal string
  173.  *          to unsigned long integer.  Returns 0xffffffff if any
  174.  *          non-hex character is encountered within the byte count,
  175.  *          or if the byte count exceeds 8.
  176.  */
  177.     unsigned long int
  178. xtol_n( string, bytes )
  179.     unsigned char   string[] ;
  180.     short int       bytes ;
  181. {
  182.     int     pt ;
  183.     unsigned long int   test_l ;        /*  value of hex expression */
  184.     unsigned char       this_hex,       /*  value of one character  */
  185.                         uc ;
  186.  
  187.     if( !bytes )
  188.         return( 0 ) ;
  189.     if( bytes > 8 )
  190.         return( 0xffffffff );
  191.  
  192.     test_l = 0 ;
  193.     for( pt = 0 ; pt < bytes ; pt++ )
  194.     {
  195.         if( !isxdigit( string[ pt ] ))
  196.             return( 0xffffffff );
  197.         uc = ( unsigned char ) string[ pt ] ;
  198.         if( isdigit( uc ))
  199.             this_hex = uc - ( unsigned char ) '0' ;
  200.         else if( isupper( uc ))
  201.             this_hex = uc - ( unsigned char ) 'A' + 10 ;
  202.         else
  203.             this_hex = uc - ( unsigned char ) 'a' + 10 ;
  204.         test_l = ( test_l << 4 ) + ( unsigned long ) this_hex ;
  205.     }
  206.  
  207.     return( test_l );
  208. }
  209. /*
  210.  *  PROCESS -   Passes through 1 file looking for key, outputting
  211.  *      [preceding and] following characters when found.
  212.  */
  213.  
  214.     void
  215. process( key, key_len, ascii, precede, fp_in )
  216.     unsigned char       key[16];    /*  characters requested by user  */
  217.     short int           key_len,
  218.                         precede;    /*  bytes before key to be shown  */
  219.     Bool                ascii ;     /*  40 bytes ASCII, no hex display*/
  220.     FILE                *fp_in ;
  221. {
  222.     unsigned char       buffer[ BIGBUF ];
  223.     Bool                need_data,
  224.                         good_key ;  /*  found a match                */
  225.     long int            cum_byt;    /*  cumulative bytes into file   */
  226.     int                 length,     /*  of buffer contents           */
  227.                         pt,         /*  current byte in buffer       */
  228.                         display,    /*  16 or 40 bytes long          */
  229.                         adjust,
  230.                         i, j, pt2 ;
  231.  
  232.     cum_byt = adjust = 0;
  233.     need_data = TRUE ;
  234.     display = 16 ;
  235.     if( ascii )
  236.         display = 40 ;
  237.  
  238.     repeat
  239.     {
  240.         if( need_data )
  241.         {
  242.             length = fread( &buffer[ adjust ], sizeof( char ),
  243.                 ( BIGBUF - adjust ), fp_in );
  244.             length += adjust;
  245.             if( !length )
  246.                 break ;
  247.             if( adjust )
  248.                 pt = precede;
  249.             else
  250.                 pt = 0 ;
  251.             adjust = 0 ;
  252.             need_data = FALSE ;
  253.  
  254.             /*  After the end of last buffer in the file, */
  255.             /*  reduce any trailing bytes to NULLs.       */
  256.  
  257.             if( length < BIGBUF )
  258.             {
  259.                 for( i= length, j= 0 ; ( i < BIGBUF && j < display ) ;
  260.                                                             i++, j++ )
  261.                     buffer[i] = '\0' ;
  262.             }
  263.         }
  264.  
  265.         if( length < BIGBUF && pt == length )
  266.             break ;         /*  Normal exit         */
  267.  
  268.         if( pt + display + 1 > length && length == BIGBUF )
  269.         {
  270.             for( adjust = 0, j = pt - precede ; j < length ; j++, 
  271.                             adjust++ )
  272.                 buffer[ adjust ] = buffer[ j ] ;
  273.             need_data = TRUE ;
  274.             continue ;
  275.         }
  276.  
  277.         if( buffer[pt] != key[0] )
  278.         {
  279.             pt++ ;
  280.             cum_byt++ ;
  281.             continue;       /*  the most typical action */
  282.         }
  283.  
  284.         good_key = TRUE ;
  285.         for( pt2 = pt + 1, i = 1 ; i < key_len ; pt2++, i++ )
  286.         {
  287.             if( buffer[pt2] != key[i] )
  288.             {
  289.                 good_key = FALSE ;
  290.                 break ;
  291.             }
  292.         }
  293.         if( good_key )
  294.             line_out( cum_byt, &buffer[ pt - precede ], ascii ) ;
  295.         pt++ ;
  296.         cum_byt++ ;
  297.     }
  298.     return;
  299. }
  300. /*
  301.  *  LINE_OUT    Output an offset followed by 16 bytes, first in
  302.  *              hexadecimal, then in printable form, with periods
  303.  *              substituting for non-printable characters.  Where
  304.  *              ASCII only is requested, 40 bytes are output.
  305.  */
  306.     void
  307. line_out( offset, buf, ascii )
  308.     long int        offset ;
  309.     unsigned char   *buf ;
  310.     Bool            ascii ;
  311. {
  312.     int         display,
  313.                 i ;
  314.  
  315.     display = 16 ;
  316.     if( ascii )
  317.         display = 40 ;
  318.  
  319.     printf( "%08ld: ", offset );
  320.     if( !ascii )
  321.     {
  322.         for( i = 0 ; i < 16 ; i++ )
  323.             printf( "%02x ", buf[ i ] );
  324.     }
  325.     printf( "   " );
  326.     for( i = 0 ; i < display ; i++ )
  327.     {
  328.         if( isprint( buf[i] ))
  329.             putchar( buf[i] );
  330.         else
  331.             putchar( '.' );
  332.     }
  333.  
  334.     /*  If we test the output once per line, */
  335.     /*  that will catch any write errors.    */
  336.  
  337.     if( putchar( '\n' ) != '\n' )
  338.     {
  339.         fprintf( stderr, "FATAL... Unable to write output.\n\n" );
  340.         exit( 1 );
  341.     }
  342.  
  343.     return ;
  344. }
  345.